package com.imut.lagain.service.impl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.imut.lagain.entity.User;
import com.imut.lagain.entity.MemoryCapsule;
import com.imut.lagain.service.ICacheService;
import com.imut.lagain.service.IPushService;
import com.imut.lagain.service.IUserService;
import com.imut.lagain.service.IWeChatService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * 消息推送服务类
 * 处理各种推送通知
 */
@Service
public class PushServiceImpl implements IPushService {
    private static final Logger log = LoggerFactory.getLogger(PushServiceImpl.class);

    
    private final IWeChatService IWeChatService;
    private final IUserService userService;
    private final WebClient webClient;
    
    @Autowired(required = false)
    private ICacheService cacheService;
    
    public PushServiceImpl(IWeChatService weChatService, IUserService userService, WebClient webClient) {
        this.IWeChatService = weChatService;
        this.userService = userService;
        this.webClient = webClient;
    }
    private static final String CAPSULE_OPEN_TEMPLATE = "capsule_open_template";
    private static final String CAPSULE_REMINDER_TEMPLATE = "capsule_reminder_template";
    private static final String SYSTEM_NOTICE_TEMPLATE = "system_notice_template";
    private static final String SECURITY_ALERT_TEMPLATE = "security_alert_template";
    /**
     * 发送胶囊开启通知
     * @param userId 用户ID
     * @param capsule 胶囊信息
     */
    @Async
    @Override
    public CompletableFuture<Boolean> sendCapsuleOpenNotification(Long userId, MemoryCapsule capsule) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                User user = userService.getById(userId);
                if (user == null || user.getOpenid() == null) {
                    log.warn("用户不存在或未绑定微信，无法发送推送: userId={}", userId);
                    return false;
                }
                Map<String, Object> data = new HashMap<>();
                data.put("thing1", Map.of("value", truncateString(capsule.getTitle(), 20)));
                data.put("time2", Map.of("value", capsule.getOpenTime().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm"))));
                data.put("thing3", Map.of("value", "您的时光胶囊已经开启，快来查看吧！"));
                boolean success = IWeChatService.sendSubscribeMessage(
                    user.getOpenid(),
                    CAPSULE_OPEN_TEMPLATE,
                    data,
                    "pages/capsule/detail?id=" + capsule.getId()
                );
                
                if (success) {
                    log.info("胶囊开启推送发送成功: userId={}, capsuleId={}", userId, capsule.getId());
                    recordPushHistory(userId, "capsule_open", capsule.getId().toString(), true);
                } else {
                    log.warn("胶囊开启推送发送失败: userId={}, capsuleId={}", userId, capsule.getId());
                    recordPushHistory(userId, "capsule_open", capsule.getId().toString(), false);
                }
                
                return success;
            } catch (Exception e) {
                log.error("发送胶囊开启推送失败: userId={}, capsuleId={}", userId, capsule.getId(), e);
                recordPushHistory(userId, "capsule_open", capsule.getId().toString(), false);
                return false;
            }
        });
    }
    
    /**
     * 发送胶囊开启提醒
     * @param userId 用户ID
     * @param capsule 胶囊信息
     * @param hoursLeft 剩余小时数
     */
    @Async
    @Override
    public CompletableFuture<Boolean> sendCapsuleOpenReminder(Long userId, MemoryCapsule capsule, long hoursLeft) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                User user = userService.getById(userId);
                if (user == null || user.getOpenid() == null) {
                    log.warn("用户不存在或未绑定微信，无法发送提醒: userId={}", userId);
                    return false;
                }
                String reminderKey = String.format("push:reminder:%d:%d:%d", userId, capsule.getId(), hoursLeft);
                if (cacheService.hasKey(reminderKey)) {
                    log.debug("已发送过相同提醒，跳过: userId={}, capsuleId={}, hoursLeft={}", userId, capsule.getId(), hoursLeft);
                    return true;
                }
                Map<String, Object> data = new HashMap<>();
                data.put("thing1", Map.of("value", truncateString(capsule.getTitle(), 20)));
                data.put("time2", Map.of("value", capsule.getOpenTime().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm"))));
                
                String reminderText;
                if (hoursLeft >= 24) {
                    reminderText = String.format("还有%d天开启", hoursLeft / 24);
                } else {
                    reminderText = String.format("还有%d小时开启", hoursLeft);
                }
                data.put("thing3", Map.of("value", reminderText));
                boolean success = IWeChatService.sendSubscribeMessage(
                    user.getOpenid(),
                    CAPSULE_REMINDER_TEMPLATE,
                    data,
                    "pages/capsule/detail?id=" + capsule.getId()
                );
                
                if (success) {
                    log.info("胶囊开启提醒发送成功: userId={}, capsuleId={}, hoursLeft={}", userId, capsule.getId(), hoursLeft);
                    cacheService.setEx(reminderKey, "sent", 3600 * 25); // 25小时过期
                    recordPushHistory(userId, "capsule_reminder", capsule.getId().toString(), true);
                } else {
                    log.warn("胶囊开启提醒发送失败: userId={}, capsuleId={}, hoursLeft={}", userId, capsule.getId(), hoursLeft);
                    recordPushHistory(userId, "capsule_reminder", capsule.getId().toString(), false);
                }
                
                return success;
            } catch (Exception e) {
                log.error("发送胶囊开启提醒失败: userId={}, capsuleId={}, hoursLeft={}", userId, capsule.getId(), hoursLeft, e);
                recordPushHistory(userId, "capsule_reminder", capsule.getId().toString(), false);
                return false;
            }
        });
    }
    
    /**
     * 发送系统通知
     * @param userId 用户ID（null表示群发）
     * @param title 通知标题
     * @param content 通知内容
     * @param page 跳转页面
     */
    @Async
    @Override
    public CompletableFuture<Integer> sendSystemNotice(Long userId, String title, String content, String page) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                List<User> targetUsers;
                
                if (userId != null) {
                    User user = userService.getById(userId);
                    if (user == null) {
                        log.warn("用户不存在，无法发送系统通知: userId={}", userId);
                        return 0;
                    }
                    targetUsers = List.of(user);
                } else {
                    targetUsers = userService.findActiveUsersWithOpenid();
                }
                
                int successCount = 0;
                
                for (User user : targetUsers) {
                    try {
                        if (user.getOpenid() == null) {
                            continue;
                        }
                        Map<String, Object> data = new HashMap<>();
                        data.put("thing1", Map.of("value", truncateString(title, 20)));
                        data.put("thing2", Map.of("value", truncateString(content, 20)));
                        data.put("time3", Map.of("value", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm"))));
                        boolean success = IWeChatService.sendSubscribeMessage(
                            user.getOpenid(),
                            SYSTEM_NOTICE_TEMPLATE,
                            data,
                            page
                        );
                        
                        if (success) {
                            successCount++;
                            recordPushHistory(user.getId(), "system_notice", title, true);
                        } else {
                            recordPushHistory(user.getId(), "system_notice", title, false);
                        }
                        Thread.sleep(100);
                        
                    } catch (Exception e) {
                        log.error("发送系统通知失败: userId={}", user.getId(), e);
                        recordPushHistory(user.getId(), "system_notice", title, false);
                    }
                }
                
                log.info("系统通知发送完成: 目标用户={}, 成功发送={}", targetUsers.size(), successCount);
                return successCount;
                
            } catch (Exception e) {
                log.error("发送系统通知失败: userId={}, title={}", userId, title, e);
                return 0;
            }
        });
    }
    
    /**
     * 发送安全警告
     * @param userId 用户ID
     * @param alertType 警告类型
     * @param alertContent 警告内容
     */
    @Async
    @Override
    public CompletableFuture<Boolean> sendSecurityAlert(Long userId, String alertType, String alertContent) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                User user = userService.getById(userId);
                if (user == null || user.getOpenid() == null) {
                    log.warn("用户不存在或未绑定微信，无法发送安全警告: userId={}", userId);
                    return false;
                }
                Map<String, Object> data = new HashMap<>();
                data.put("thing1", Map.of("value", alertType));
                data.put("thing2", Map.of("value", truncateString(alertContent, 20)));
                data.put("time3", Map.of("value", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm"))));
                boolean success = IWeChatService.sendSubscribeMessage(
                    user.getOpenid(),
                    SECURITY_ALERT_TEMPLATE,
                    data,
                    "pages/user/security"
                );
                
                if (success) {
                    recordPushHistory(userId, "security_alert", alertType, true);
                } else {
                    log.warn("安全警告推送发送失败: userId={}, alertType={}", userId, alertType);
                    recordPushHistory(userId, "security_alert", alertType, false);
                }
                
                return success;
            } catch (Exception e) {
                log.error("发送安全警告推送失败: userId={}, alertType={}", userId, alertType, e);
                recordPushHistory(userId, "security_alert", alertType, false);
                return false;
            }
        });
    }
    /**
     * 批量发送胶囊开启提醒
     * @param capsules 胶囊列表
     * @param hoursLeft 剩余小时数
     */
    @Async
    @Override
    public CompletableFuture<Integer> batchSendCapsuleReminders(List<MemoryCapsule> capsules, long hoursLeft) {
        return CompletableFuture.supplyAsync(() -> {
            int successCount = 0;
            
            for (MemoryCapsule capsule : capsules) {
                try {
                    CompletableFuture<Boolean> result = sendCapsuleOpenReminder(capsule.getUserId(), capsule, hoursLeft);
                    if (result.get()) {
                        successCount++;
                    }
                    Thread.sleep(200);
                    
                } catch (Exception e) {
                    log.error("批量发送胶囊提醒失败: capsuleId={}", capsule.getId(), e);
                }
            }
            
            log.info("批量胶囊提醒发送完成: 目标胶囊={}, 成功发送={}", capsules.size(), successCount);
            return successCount;
        });
    }
    
    /**
     * 批量发送胶囊开启通知
     * @param capsules 胶囊列表
     */
    @Async
    @Override
    public CompletableFuture<Integer> batchSendCapsuleOpenNotifications(List<MemoryCapsule> capsules) {
        return CompletableFuture.supplyAsync(() -> {
            int successCount = 0;
            
            for (MemoryCapsule capsule : capsules) {
                try {
                    CompletableFuture<Boolean> result = sendCapsuleOpenNotification(capsule.getUserId(), capsule);
                    if (result.get()) {
                        successCount++;
                    }
                    Thread.sleep(200);
                    
                } catch (Exception e) {
                    log.error("批量发送胶囊开启通知失败: capsuleId={}", capsule.getId(), e);
                }
            }
            
            log.info("批量胶囊开启通知发送完成: 目标胶囊={}, 成功发送={}", capsules.size(), successCount);
            return successCount;
        });
    }
    /**
     * 获取用户推送历史
     * @param userId 用户ID
     * @param limit 限制数量
     * @return 推送历史列表
     */
    @Override
    public List<Object> getUserPushHistory(Long userId, int limit) {
        try {
            String historyKey = String.format("push:history:%d", userId);
            return cacheService.lRange(historyKey, 0, limit - 1);
        } catch (Exception e) {
            log.error("获取用户推送历史失败: userId={}", userId, e);
            return List.of();
        }
    }
    
    /**
     * 获取推送统计
     * @param pushType 推送类型
     * @param days 统计天数
     * @return 统计数据
     */
    @Override
    public Map<String, Object> getPushStats(String pushType, int days) {
        Map<String, Object> stats = new HashMap<>();
        
        try {
            LocalDateTime now = LocalDateTime.now();
            long totalSuccess = 0;
            long totalFailed = 0;
            
            for (int i = 0; i < days; i++) {
                String date = now.minusDays(i).toLocalDate().toString();
                String statsKey = String.format("push:stats:%s:%s", pushType, date);
                
                Object success = cacheService.hGet(statsKey, "success");
                Object failed = cacheService.hGet(statsKey, "failed");
                
                if (success != null) {
                    totalSuccess += Long.parseLong(success.toString());
                }
                if (failed != null) {
                    totalFailed += Long.parseLong(failed.toString());
                }
            }
            
            stats.put("totalSuccess", totalSuccess);
            stats.put("totalFailed", totalFailed);
            stats.put("totalSent", totalSuccess + totalFailed);
            stats.put("successRate", totalSuccess + totalFailed > 0 ? 
                (double) totalSuccess / (totalSuccess + totalFailed) * 100 : 0);
            
        } catch (Exception e) {
            log.error("获取推送统计失败: pushType={}", pushType, e);
            stats.put("error", e.getMessage());
        }
        
        return stats;
    }
    
    /**
     * 检查用户推送权限
     * @param userId 用户ID
     * @param pushType 推送类型
     * @return 是否有权限
     */
    @Override
    public boolean checkPushPermission(Long userId, String pushType) {
        try {
            User user = userService.getById(userId);
            if (user == null) {
                return false;
            }
            String permissionKey = String.format("push:permission:%d:%s", userId, pushType);
            Object permission = cacheService.get(permissionKey);
            return permission == null || Boolean.parseBoolean(permission.toString());
            
        } catch (Exception e) {
            log.error("检查推送权限失败: userId={}, pushType={}", userId, pushType, e);
            return false;
        }
    }
    
    /**
     * 设置用户推送权限
     * @param userId 用户ID
     * @param pushType 推送类型
     * @param enabled 是否启用
     */
    @Override
    public void setPushPermission(Long userId, String pushType, boolean enabled) {
        try {
            String permissionKey = String.format("push:permission:%d:%s", userId, pushType);
            cacheService.setEx(permissionKey, String.valueOf(enabled), 86400 * 365); // 1年过期
        } catch (Exception e) {
            log.error("设置推送权限失败: userId={}, pushType={}", userId, pushType, e);
        }
    }
    /**
     * 检查推送服务是否可用
     * @return 是否可用
     */
    @Override
    public boolean isPushServiceAvailable() {
        try {
            return IWeChatService.isWeChatServiceAvailable();
        } catch (Exception e) {
            log.error("检查推送服务可用性失败", e);
            return false;
        }
    }
    
    /**
     * 获取推送服务状态
     * @return 服务状态
     */
    @Override
    public Map<String, Object> getPushServiceStatus() {
        Map<String, Object> status = new HashMap<>();
        
        try {
            status.put("available", isPushServiceAvailable());
            status.put("wechatServiceStatus", IWeChatService.getServiceStatus());
            String today = LocalDateTime.now().toLocalDate().toString();
            status.put("todayStats", Map.of(
                "capsuleOpen", getPushStats("capsule_open", 1),
                "capsuleReminder", getPushStats("capsule_reminder", 1),
                "systemNotice", getPushStats("system_notice", 1),
                "securityAlert", getPushStats("security_alert", 1)
            ));
            
        } catch (Exception e) {
            log.error("获取推送服务状态失败", e);
            status.put("error", e.getMessage());
        }
        
        return status;
    }
    
    /**
     * 记录推送历史
     *
     * @param userId   用户ID
     * @param pushType 推送类型
     * @param content  推送内容
     * @param success  是否成功
     */
    @Override
    public void recordPushHistory(Long userId, String pushType, String content, boolean success) {
        try {
            String historyKey = String.format("push:history:%d", userId);
            Map<String, Object> record = new HashMap<>();
            record.put("type", pushType);
            record.put("content", content);
            record.put("success", success);
            record.put("timestamp", LocalDateTime.now().toString());
            cacheService.lPush(historyKey, record);
            cacheService.lTrim(historyKey, 0, 99);
            cacheService.expire(historyKey, 86400 * 30, java.util.concurrent.TimeUnit.SECONDS); // 30天过期
            String statsKey = String.format("push:stats:%s:%s", pushType, LocalDateTime.now().toLocalDate());
            if (success) {
                cacheService.hIncr(statsKey, "success", 1);
            } else {
                cacheService.hIncr(statsKey, "failed", 1);
            }
            cacheService.expire(statsKey, 86400 * 7, java.util.concurrent.TimeUnit.SECONDS); // 7天过期

        } catch (Exception e) {
            log.error("记录推送历史失败: userId={}, pushType={}", userId, pushType, e);
        }
    }
    
    /**
     * 截断字符串到指定长度
     *
     * @param str       原字符串
     * @param maxLength 最大长度
     * @return 截断后的字符串
     */
    @Override
    public String truncateString(String str, int maxLength) {
        if (str == null) {
            return "";
        }
        if (str.length() <= maxLength) {
            return str;
        }
        return str.substring(0, maxLength - 3) + "...";
    }
}

